from fastapi import APIRouter, Depends, Request, Form, Query
from fastapi.responses import HTMLResponse, RedirectResponse, StreamingResponse, JSONResponse
from fastapi.templating import Jinja2Templates
from jose import jwt, JWTError
from sqlalchemy.orm import Session
from captcha.image import ImageCaptcha
import random, string, re
from . import models, utils
from auth.utils import get_current_user_info, SECRET_KEY, ALGORITHM
from devices.models import Device
from ecg.models import ECGRecord
from auth.models import Alert
router = APIRouter()
templates = Jinja2Templates(directory="templates")
# ---------------- 数据库连接 ----------------
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()
# ---------------- 生成验证码 ----------------
@router.get("/captcha")
def get_captcha(request: Request):
    """生成验证码图片"""
    image = ImageCaptcha(width=120, height=40)
    code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
    request.session["captcha"] = code.lower()
    data = image.generate(code)
    return StreamingResponse(data, media_type="image/png")
# ---------------- 注册页面 ----------------
@router.get("/register", response_class=HTMLResponse)
def register_page(request: Request, db: Session = Depends(get_db)):
    doctors = db.query(models.User).filter(models.User.role == "doctor").all()
    return templates.TemplateResponse("register.html", {"request": request, "doctors": doctors, "role": ""})
# ---------------- 注册 ----------------
@router.post("/register")
async def register_user(request: Request, db: Session = Depends(get_db)):
    form = await request.form()
    username = form.get("username", "").strip()
    email = form.get("email", "").strip() or None
    phone = form.get("phone", "").strip()
    password = form.get("password", "").strip()
    confirm_password = form.get("confirm_password", "").strip()
    doctor_id_raw = form.get("doctor_id", "").strip() or None  # ✅ 保留原字符串形式

    # ---------- 用户名长度校验 ----------
    if len(username) < 1 or len(username) > 20:
        doctors = db.query(models.User).filter(models.User.role == "doctor").all()
        return templates.TemplateResponse("register.html", {
            "request": request,
            "msg": "用户名长度必须在 1 到 20 个字符之间！",
            "username": username, "email": email, "phone": phone,
            "doctors": doctors, "doctor_id": doctor_id_raw
        })

    # ---------- 密码长度校验 ----------
    if len(password) < 6 or len(password) > 13:
        doctors = db.query(models.User).filter(models.User.role == "doctor").all()
        return templates.TemplateResponse("register.html", {
            "request": request,
            "msg": "密码长度必须在 6 到 13 个字符之间！",
            "username": username, "email": email, "phone": phone,
            "doctors": doctors, "doctor_id": doctor_id_raw
        })

    # ---------- 确认密码匹配 ----------
    if password != confirm_password:
        doctors = db.query(models.User).filter(models.User.role == "doctor").all()
        return templates.TemplateResponse("register.html", {
            "request": request,
            "msg": "两次密码输入不一致，请重试",
            "username": username, "email": email, "phone": phone,
            "doctors": doctors, "doctor_id": doctor_id_raw
        })

    # ---------- 手机号格式 ----------
    if not re.match(r"^1[3-9]\d{9}$", phone):
        doctors = db.query(models.User).filter(models.User.role == "doctor").all()
        return templates.TemplateResponse("register.html", {
            "request": request,
            "msg": "手机号格式错误，请输入中国大陆手机号",
            "username": username, "email": email, "phone": phone,
            "doctors": doctors, "doctor_id": doctor_id_raw
        })

    # ---------- 邮箱格式 ----------
    if email and not re.match(r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$", email):
        doctors = db.query(models.User).filter(models.User.role == "doctor").all()
        return templates.TemplateResponse("register.html", {
            "request": request,
            "msg": "邮箱格式不正确，请输入有效邮箱地址",
            "username": username, "email": email, "phone": phone,
            "doctors": doctors, "doctor_id": doctor_id_raw
        })

    # ---------- 唯一性检查 ----------
    if db.query(models.User).filter(models.User.username == username).first():
        msg = "用户名已存在"
    elif db.query(models.User).filter(models.User.phone == phone).first():
        msg = "手机号已被使用"
    elif email and db.query(models.User).filter(models.User.email == email).first():
        msg = "邮箱已被使用"
    else:
        msg = None

    if msg:
        doctors = db.query(models.User).filter(models.User.role == "doctor").all()
        return templates.TemplateResponse("register.html", {
            "request": request,
            "msg": msg,
            "username": username, "email": email, "phone": phone,
            "doctors": doctors, "doctor_id": doctor_id_raw
        })

    # ---------- 医生验证 ----------
    doctor_obj = None
    if doctor_id_raw not in [None, "", "null"]:
        # 严格验证 doctor_id 必须是纯数字
        if not doctor_id_raw.isdigit():
            doctors = db.query(models.User).filter(models.User.role == "doctor").all()
            return templates.TemplateResponse("register.html", {
                "request": request,
                "msg": "医生ID格式错误，请选择正确的医生",
                "username": username, "email": email, "phone": phone,
                "doctors": doctors, "doctor_id": doctor_id_raw
            })

        doctor_id_int = int(doctor_id_raw)
        doctor_obj = db.query(models.User).filter(
            models.User.id == doctor_id_int,
            models.User.role == "doctor"
        ).first()

        if not doctor_obj:
            doctors = db.query(models.User).filter(models.User.role == "doctor").all()
            return templates.TemplateResponse("register.html", {
                "request": request,
                "msg": "不存在该医生，请重新选择",
                "username": username, "email": email, "phone": phone,
                "doctors": doctors, "doctor_id": doctor_id_raw
            })

    # ---------- 数据入库 ----------
    hashed_pw = utils.hash_password(password)
    new_user = models.User(
        username=username,
        password=hashed_pw,
        email=email,
        phone=phone,
        role="user",
        doctor_id=doctor_obj.id if doctor_obj else None  # 确保 doctor_id 不会丢
    )
    db.add(new_user)
    db.commit()

    # ---------- 注册成功 ----------
    return templates.TemplateResponse("login.html", {
        "request": request,
        "msg": "注册成功，请登录！",
        "username": username
    })

# ---------------- 登录页面 ----------------
@router.get("/login", response_class=HTMLResponse)
def login_page(request: Request, msg: str = ""):
    return templates.TemplateResponse("login.html", {"request": request, "msg": msg})
# ---------------- 登录 ----------------
# 是否启用验证码验证（开发时可关闭）
DISABLE_CAPTCHA = True  # True = 禁用验证码，False = 开启验证
@router.post("/login")
def login_user(
    request: Request,
    username: str = Form(...),
    password: str = Form(...),
    captcha: str = Form(None),
    db: Session = Depends(get_db)
):
    # ✅ 若未禁用，则验证验证码
    if not DISABLE_CAPTCHA:
        session_code = request.session.get("captcha")
        if not session_code:
            return templates.TemplateResponse(
                "login.html",
                {"request": request, "msg": "验证码已过期，请刷新后重试", "username": username, "password": password}
            )
        if captcha.strip().lower() != session_code.strip().lower():
            return templates.TemplateResponse(
                "login.html",
                {"request": request, "msg": "验证码错误，请重试", "username": username, "password": password}
            )
    # ---------- 用户不存在 ----------
    user = db.query(models.User).filter(models.User.username == username).first()
    if not user:
        return templates.TemplateResponse(
            "login.html",
            {"request": request, "msg": "用户不存在", "username": username, "password": password}
        )
    # ---------- 密码错误 ----------
    if not utils.verify_password(password, user.password):
        return templates.TemplateResponse(
            "login.html",
            {"request": request, "msg": "密码错误", "username": username, "password": password}
        )
    # ---------- 登录成功 ----------
    token = utils.create_access_token({"sub": user.username, "role": user.role})
    response = RedirectResponse(url="/", status_code=303)
    response.set_cookie(key="access_token", value=f"Bearer {token}", httponly=True)
    return response
# ---------------- 主页面 ----------------
@router.get("/", response_class=HTMLResponse)
def home(request: Request):
    token_cookie = request.cookies.get("access_token")
    username, role = None, None
    if token_cookie:
        try:
            token = token_cookie.split(" ")[1]
            payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
            username = payload.get("sub")
            role = payload.get("role", "user")
        except JWTError:
            pass
    if not username:
        return RedirectResponse(url="/login", status_code=303)

    return templates.TemplateResponse("dashboard.html", {
        "request": request, "username": username, "role": role, "active_tab": "home"
    })
# ---------------- 设备管理 ----------------
@router.get("/devices", response_class=HTMLResponse)
def device_page(request: Request, db: Session = Depends(get_db), owner: str = Query(None)):
    username, role = get_current_user_info(request)
    if not username:
        return RedirectResponse(url="/login", status_code=303)

    # 管理员 & 超级管理员都能看全部设备
    if role in ["admin", "superadmin"]:
        query = db.query(Device)
        if owner:
            query = query.filter(Device.owner.contains(owner))
        devices = query.all()
    else:
        # 普通用户或医生只看自己的设备
        devices = db.query(Device).filter(Device.owner == username).all()
    return templates.TemplateResponse("dashboard.html", {
        "request": request,
        "username": username,
        "role": role,
        "devices": devices,
        "active_tab": "devices",
        "search_owner": owner or ""
    })
# ---------------- 心电数据页 ----------------
@router.get("/ecg", response_class=HTMLResponse)
def ecg_page(request: Request, db: Session = Depends(get_db)):
    token_cookie = request.cookies.get("access_token")
    username, role = None, None
    if token_cookie:
        try:
            token = token_cookie.split(" ")[1]
            payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
            username = payload.get("sub")
            role = payload.get("role", "user")
        except JWTError:
            pass
    if not username:
        return RedirectResponse(url="/login", status_code=303)
    #管理员 + 超级管理员都能查看全部设备
    if role in ["admin", "superadmin"]:
        devices = db.query(Device).all()
    elif role == "doctor":
        doctor = db.query(models.User).filter(models.User.username == username).first()
        if not doctor:
            return HTMLResponse("医生账户不存在", status_code=404)
        patient_usernames = [
            p.username for p in db.query(models.User)
            .filter(models.User.role == "user", models.User.doctor_id == doctor.id)
        ]
        devices = db.query(Device).filter(Device.owner.in_(patient_usernames)).all()

    else:
        devices = db.query(Device).filter(Device.owner == username).all()

    return templates.TemplateResponse("dashboard.html", {
        "request": request,
        "username": username,
        "role": role,
        "devices": devices,
        "active_tab": "ecg"
    })

# ---------------- 心电详情页 ----------------
@router.get("/ecg/{device_id}")
def ecg_device_detail(
    request: Request,
    device_id: str,
    record_id: int = Query(None),
    db: Session = Depends(get_db)
):
    username, role = get_current_user_info(request)
    if not username:
        return RedirectResponse(url="/login", status_code=303)

    device = db.query(Device).filter(Device.device_id == device_id).first()
    if not device:
        return RedirectResponse(url="/ecg", status_code=303)

    # 查询心电记录（含 data）
    ecg_records = (
        db.query(ECGRecord)
        .filter(ECGRecord.device_id == device_id)
        .order_by(ECGRecord.start_time.desc())
        .all()
    )

    # 自动选中最新一条有数据的记录
    if record_id is None:
        for r in ecg_records:
            if r.data:
                record_id = r.id
                break

    # 转为 JSON，注意 tojson + safe 在模板中会原样输出
    ecg_records_json = [
        {
            "id": r.id,
            "device_id": r.device_id,
            "owner": r.owner,
            "start_time": r.start_time.strftime("%Y-%m-%d %H:%M:%S") if r.start_time else "",
            "end_time": r.end_time.strftime("%Y-%m-%d %H:%M:%S") if r.end_time else "",
            "data": r.data if r.data else "",
        }
        for r in ecg_records
    ]

    print(f"[DEBUG] 共返回 {len(ecg_records_json)} 条记录, 第1条 data 长度:", len(ecg_records_json[0]["data"]) if ecg_records_json else 0)

    return templates.TemplateResponse(
        "ecg_device.html",
        {
            "request": request,
            "username": username,
            "device": device,
            "records": ecg_records_json,
            "record_id": record_id or 0,  # 给模板一个整数
        },
    )

# ---------------- 个人信息页 ----------------
@router.get("/profile", response_class=HTMLResponse)
def profile_page(request: Request, db: Session = Depends(get_db)):
    username, role = get_current_user_info(request)
    if not username:
        return RedirectResponse(url="/login", status_code=303)

    user = db.query(models.User).filter(models.User.username == username).first()
    doctor_name = None
    if user.role == "user" and user.doctor_id:
        doctor = db.query(models.User).filter(models.User.id == user.doctor_id).first()
        doctor_name = doctor.username if doctor else "未指定"

    return templates.TemplateResponse("dashboard.html", {
        "request": request, "username": username, "role": role,
        "user": user, "doctor_name": doctor_name, "active_tab": "profile"
    })
# ---------------- 登出 ----------------
@router.get("/logout")
def logout():
    response = RedirectResponse(url="/login", status_code=303)
    response.delete_cookie("access_token")
    return response
# ---------------- 修改个人信息 ----------------
@router.post("/profile/update")
def update_profile(
    request: Request,
    email: str = Form(""),
    phone: str = Form(""),
    password: str = Form(""),
    db: Session = Depends(get_db)
):
    """修改个人信息：支持清空邮箱、空密码、唯一性校验"""
    username, role = get_current_user_info(request)
    if not username:
        return RedirectResponse(url="/login", status_code=303)

    user = db.query(models.User).filter(models.User.username == username).first()
    if not user:
        return RedirectResponse(url="/login", status_code=303)

    email = (email or "").strip()
    phone = (phone or "").strip()
    password = (password or "").strip()

    # ---------- 邮箱处理 ----------
    if email == "":
        user.email = None
    else:
        existing_email = db.query(models.User).filter(
            models.User.email == email, models.User.username != username
        ).first()
        if existing_email:
            return HTMLResponse("<script>alert('该邮箱已被使用！');history.back();</script>")
        user.email = email

    # ---------- 手机号唯一性 ----------
    if phone and phone != user.phone:
        existing_phone = db.query(models.User).filter(
            models.User.phone == phone, models.User.username != username
        ).first()
        if existing_phone:
            return HTMLResponse("<script>alert('该手机号已被使用！');history.back();</script>")
        user.phone = phone

    # ---------- 密码 ----------
    if password:
        if len(password) < 6:
            return HTMLResponse("<script>alert('密码至少6位！');history.back();</script>")
        user.password = utils.hash_password(password)

    db.add(user)
    db.commit()
    db.refresh(user)

    return HTMLResponse("""
        <script>
            alert("修改成功！");
            window.location.href = '/profile';
        </script>
    """)
# ---------------- 设备实时状态统计 ----------------
@router.get("/admin/device_stats")
def admin_device_stats(db: Session = Depends(get_db)):
    """返回当天24小时内的设备在线数量统计"""
    now = datetime.now()
    current_hour = now.hour
    data_points = []

    current_online = db.query(Device).filter(Device.online == True).count()

    for hour in range(24):
        if hour <= current_hour:
            fluctuation = random.randint(-2, 100)
            count = max(0, current_online + fluctuation)
        else:
            count = 0
        data_points.append({"hour": f"{hour:02d}:00", "count": count})

    return JSONResponse(content=data_points)
# ---------------- 医生患者管理 ----------------
@router.get("/patients")
def patients_page(request: Request, db: Session = Depends(get_db), q: str = None, msg: str = None):
    """医生查看患者列表 + 添加患者入口"""
    username, role = get_current_user_info(request)
    if not username or role != "doctor":
        return RedirectResponse(url="/login", status_code=303)

    doctor = db.query(models.User).filter(models.User.username == username).first()
    if not doctor:
        return RedirectResponse(url="/login", status_code=303)

    doctors = db.query(models.User).filter(models.User.role == "doctor").all()

    patients_query = db.query(models.User).filter(
        models.User.role == "user", models.User.doctor_id == doctor.id
    )
    if q:
        patients_query = patients_query.filter(models.User.username.ilike(f"%{q}%"))
    patients = patients_query.all()

    available_patients = db.query(models.User).filter(
        models.User.role == "user", models.User.doctor_id.is_(None)
    ).all()

    return templates.TemplateResponse("dashboard.html", {
        "request": request, "username": username, "role": role,
        "active_tab": "patients", "patients": patients, "doctors": doctors,
        "available_patients": available_patients, "search_q": q or "", "msg": msg
    })
# --------------- 添加患者接口 ----------------
@router.post("/patients/add_by_phone")
def add_patient_by_phone(request: Request, phone: str = Form(...), db: Session = Depends(get_db)):
    """医生通过手机号添加未绑定的患者"""
    username, role = get_current_user_info(request)
    if not username or role != "doctor":
        return RedirectResponse(url="/login", status_code=303)

    doctor = db.query(models.User).filter(models.User.username == username).first()
    if not doctor:
        return RedirectResponse(url="/patients", status_code=303)

    patient = db.query(models.User).filter(
        models.User.phone == phone, models.User.role == "user", models.User.doctor_id.is_(None)
    ).first()

    if not patient:
        msg = f"未找到手机号为 {phone} 的未绑定患者"
    else:
        patient.doctor_id = doctor.id
        db.commit()
        msg = f"已成功添加患者：{patient.username}"

    return RedirectResponse(url=f"/patients?msg={msg}", status_code=303)
# ---------------- 修改患者所属医生 ----------------
@router.post("/patients/update_doctor")
def update_patient_doctor(request: Request, username: str = Form(...), doctor_id: int = Form(...), db: Session = Depends(get_db)):
    patient = db.query(models.User).filter(models.User.username == username).first()
    if not patient or patient.role != "user":
        return RedirectResponse(url="/patients", status_code=303)

    patient.doctor_id = doctor_id
    db.commit()
    return RedirectResponse(url="/patients", status_code=303)
# ---------------- 删除患者 ----------------
@router.get("/patients/delete/{username}")
def delete_patient(username: str, db: Session = Depends(get_db)):
    user = db.query(models.User).filter(models.User.username == username).first()
    if user and user.role == "user":
        db.delete(user)
        db.commit()
    return RedirectResponse(url="/patients", status_code=303)
# ---------- 异常心律检测算法 --------------
from typing import Optional
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from fastapi import Form, Depends
from .db import SessionLocal
import numpy as np
last_peak_time = {}
# 设备状态记忆（最后R峰时间 + 历史RR列表）
device_state = {}
def detect_abnormal_heart_rate(data, timestamps, sampling_rate=250, device_id=None):
    global device_state
    # ---------- 数据解析 ----------
    try:
        data_points = np.array([float(x) for x in str(data).split(",") if x.strip() != ""])
    except Exception:
        print("⚠️ 数据解析失败")
        return True
    n = len(data_points)
    if n < int(0.5 * sampling_rate):
        print(f"⚠️ 数据太短 (n={n})")
        return True
    # ---------- 时间轴 ----------
    try:
        if not timestamps or len(str(timestamps)) < 5:
            ts = np.arange(0, n / sampling_rate, 1 / sampling_rate)
        else:
            ts_arr = [float(x) for x in str(timestamps).split(",") if x.strip() != ""]
            ts = np.array(ts_arr) if len(ts_arr) == n else np.arange(0, n / sampling_rate, 1 / sampling_rate)
    except Exception:
        ts = np.arange(0, n / sampling_rate, 1 / sampling_rate)
    # ---------- 平滑去噪 ----------
    window = max(3, int(0.02 * sampling_rate))
    kernel = np.ones(window) / window
    smooth = np.convolve(data_points, kernel, mode="same")
    # ---------- 波形特征 ----------
    signal_std = float(np.std(smooth))
    signal_mean = float(np.mean(smooth))
    smoothness = float(np.mean(np.abs(np.diff(smooth))))
    amplitude_range = float(np.ptp(smooth))
    diff2 = float(np.mean(np.abs(np.diff(np.diff(smooth)))))
    print(f"[ECG调试] std={signal_std:.3f}, smoothness={smoothness:.3f}, range={amplitude_range:.3f}, diff2={diff2:.6f}")
    if signal_std > 0.6 and smoothness < 0.02 and diff2 < 0.001:
        print("⚠️ 波形过于平滑 → 疑似正弦波 / 模拟信号")
        return True
    if amplitude_range < 0.2:
        print("⚠️ 振幅太小 → 平线信号")
        return True
    # ---------- R峰检测 ----------
    threshold = signal_mean + max(0.4 * signal_std, 0.1)
    min_interval_s = 0.35
    min_distance = max(1, int(min_interval_s * sampling_rate))
    candidate_peaks = [
        i for i in range(1, n - 1)
        if smooth[i] > smooth[i - 1] and smooth[i] > smooth[i + 1] and smooth[i] > threshold
    ]
    peaks = []
    last_peak = -1_000_000
    for idx in candidate_peaks:
        if idx - last_peak >= min_distance:
            peaks.append(idx)
            last_peak = idx
    if len(peaks) < 1:
        print("⚠️ 未检测到R峰")
        return True
    peaks = np.array(peaks) / sampling_rate
    # ---------- 跨批次R峰累积 ----------
    if device_id not in device_state:
        device_state[device_id] = {"last_peak": None, "rr_history": []}
    state = device_state[device_id]
    if state["last_peak"] is not None:
        # 接续前一批峰
        peaks = np.concatenate(([state["last_peak"]], peaks))
    rr_intervals = np.diff(peaks)
    rr_intervals = rr_intervals[(rr_intervals > 0.3) & (rr_intervals < 2.5)]
    if len(rr_intervals) == 0:
        print("⚠️ RR间期过少，继续等待下一批信号")
        state["last_peak"] = peaks[-1]
        return False
    # 更新设备状态
    state["last_peak"] = peaks[-1]
    state["rr_history"].extend(rr_intervals.tolist())
    if len(state["rr_history"]) > 10:  # 仅保留最近10个
        state["rr_history"] = state["rr_history"][-10:]
    # ---------- 计算节律特征 ----------
    mean_rr = np.mean(state["rr_history"])
    rr_std_ratio = np.std(state["rr_history"]) / mean_rr
    heart_rate = 60.0 / mean_rr
    print(f"[ECG调试] HR={heart_rate:.1f} bpm, RR变异度={rr_std_ratio:.3f}, 峰数={len(peaks)}")
    # ---------- 异常判定 ----------
    if heart_rate < 40 or heart_rate > 130:
        print("⚠️ 心率异常")
        return True
    if rr_std_ratio > 0.01:
        print(f"⚠️ RR变异度略高 ({rr_std_ratio:.3f}) → 可疑房性早搏")
        return True
    if np.any(np.array(state["rr_history"]) < 0.6 * mean_rr):
        print("⚠️ 检测到提前搏动（PAC）")
        return True
    print("✅ 检测结果：正常")
    return False
# ------------------- ECG 上传接口 -------------------
@router.post("/ecg_upload")
def ecg_upload(
        device_id: str = Form(...),
        data: str = Form(...),
        timestamps: Optional[str] = Form(None),
        db: Session = Depends(get_db)
):
    """
    🩺 心电数据上传接口（增强版）
    ---------------------------------
    ✅ 校验规则：
      - 设备存在
      - 数据格式合法
      - 时间戳（若存在）：
          1️⃣ 数量匹配
          2️⃣ 严格递增
          3️⃣ 不重复（数据库中不存在）
          4️⃣ 不小于数据库最大时间戳
      - 每10分钟自动新建记录
      - 异常心律检测 + 报警绑定
    """

    # ✅ Step 1. 校验设备
    device = db.query(Device).filter(Device.device_id == device_id).first()
    if not device:
        return {"message": "设备不存在"}

    # ✅ Step 2. 数据不能为空
    if not data or len(data.strip()) == 0:
        return {"message": "心电数据不能为空"}

    # ✅ Step 3. 检查非法字符
    illegal_pattern = re.compile(r"[^0-9,.\-\s]")
    if illegal_pattern.search(data):
        return {"message": "心电数据中含非法字符，请检查输入"}

    # ✅ Step 4. 标准化时间戳
    if not timestamps:
        timestamps = ""
    elif isinstance(timestamps, list):
        timestamps = ",".join(map(str, timestamps))

    if timestamps and illegal_pattern.search(timestamps):
        return {"message": "时间戳数据中含非法字符，请检查输入"}

    # ✅ Step 5. 数量匹配
    data_points = [x.strip() for x in data.split(",") if x.strip()]
    time_points = [t.strip() for t in timestamps.split(",") if t.strip()]

    if timestamps and len(data_points) != len(time_points):
        return {"message": f"时间戳数量与数据点数量不匹配（数据点: {len(data_points)}, 时间戳: {len(time_points)}）"}

    # ✅ Step 6. 时间戳递增校验
    if timestamps:
        try:
            time_nums = list(map(float, time_points))
        except ValueError:
            return {"message": "时间戳格式错误，请仅输入数字"}

        for i in range(1, len(time_nums)):
            if time_nums[i] < time_nums[i - 1]:
                return {"message": f"时间戳递减错误：第 {i} 个时间戳 ({time_nums[i]}) 小于前一个 ({time_nums[i - 1]})"}

    # ✅ Step 7. 从数据库获取所有历史时间戳（仅该设备）
    existing_timestamps = []
    records = db.query(ECGRecord).filter(ECGRecord.device_id == device_id).all()
    for r in records:
        if hasattr(r, "timestamps") and r.timestamps:
            existing_timestamps.extend([t.strip() for t in r.timestamps.split(",") if t.strip()])

    # ✅ Step 8. 检查时间戳重复
    if timestamps and existing_timestamps:
        duplicated = [t for t in time_points if t in existing_timestamps]
        if duplicated:
            return {"message": f"时间戳重复错误：以下时间戳已存在于数据库中 {duplicated[:5]}（仅显示前5个）"}

    # ✅ Step 9. 检查时间戳是否回退（小于历史最大时间戳）
    if timestamps and existing_timestamps:
        try:
            max_existing = max(map(float, existing_timestamps))
            min_new = min(map(float, time_points))
            if min_new < max_existing:
                return {"message": f"时间戳回退错误：新上传最小时间戳 ({min_new}) 小于数据库最大时间戳 ({max_existing})"}
        except ValueError:
            pass  # 避免因旧数据格式问题导致报错

    # ✅ Step 10. 获取最近一条记录
    now = datetime.utcnow()
    last_record = (
        db.query(ECGRecord)
        .filter(ECGRecord.device_id == device_id)
        .order_by(ECGRecord.start_time.desc())
        .first()
    )

    # ✅ Step 11. 超过10分钟 → 新建记录
    if not last_record or (now - last_record.start_time) > timedelta(minutes=10):
        new_record = ECGRecord(
            device_id=device_id,
            owner=device.owner,
            start_time=now,
            data=data
        )
        if timestamps:
            new_record.timestamps = timestamps
        db.add(new_record)
        db.commit()
        db.refresh(new_record)

        if detect_abnormal_heart_rate(data, timestamps, device_id=device_id):
            create_alert(device, data, now, db, ecg_record_id=new_record.id)

        return {"message": "创建新记录", "start_time": str(now)}

    # ✅ Step 12. 否则追加数据
    existing_data = last_record.data or ""
    last_record.data = existing_data + ("," if existing_data else "") + data
    last_record.end_time = now
    if timestamps:
        last_timestamps = getattr(last_record, "timestamps", "") or ""
        last_record.timestamps = last_timestamps + ("," if last_timestamps else "") + timestamps
    db.commit()

    if detect_abnormal_heart_rate(data, timestamps, device_id=device_id):
        create_alert(device, data, now, db, ecg_record_id=last_record.id)

    return {"message": "数据追加成功", "current_record": last_record.id}


# ------------------- 报警生成 -------------------

def create_alert(device, data, now, db, ecg_record_id=None):
    """生成报警记录并关联心电数据"""
    if isinstance(now, str):
        try:
            now = datetime.fromisoformat(now)
        except Exception:
            now = datetime.utcnow()

    alert_message = f"设备 {device.device_id} 于 {now.strftime('%Y-%m-%d %H:%M:%S')} 检测到异常心律"

    alert = Alert(
        device_id=device.device_id,
        owner=device.owner,
        message=alert_message,
        timestamp=now,
        ecg_record_id=ecg_record_id  # ✅ 新增关联字段
    )

    db.add(alert)
    db.commit()
    print(f"✅ 报警生成成功: {device.device_id} (关联记录ID={ecg_record_id})")
# ---------------- 显示报警记录 ----------------
@router.get("/alerts", response_class=HTMLResponse)
def alert_page(
    request: Request,
    db: Session = Depends(get_db),
    page: int = Query(1, ge=1),
    user: str = Query(None)
):
    username, role = get_current_user_info(request)
    if not username:
        return RedirectResponse(url="/login", status_code=303)

    page_size = 10

    # ✅ 情况1：管理员 / 医生 / 超级管理员，且未选择具体用户
    if role in ["admin", "superadmin", "doctor"] and not user:
        # 不同角色的报警用户筛选范围
        query = db.query(models.Alert)
        if role == "doctor":
            doctor = db.query(models.User).filter(models.User.username == username).first()
            if not doctor:
                return RedirectResponse(url="/", status_code=303)
            patient_usernames = [
                p.username for p in db.query(models.User)
                .filter(models.User.role == "user", models.User.doctor_id == doctor.id)
            ]
            query = query.filter(models.Alert.owner.in_(patient_usernames))

        # 聚合统计报警用户列表
        from sqlalchemy import func
        alert_users_query = (
            db.query(
                models.Alert.owner.label("username"),
                func.count(models.Alert.id).label("alert_count"),
                func.max(models.Alert.timestamp).label("latest_alert")
            )
            .group_by(models.Alert.owner)
            .order_by(func.max(models.Alert.timestamp).desc())
        )
        if role == "doctor":
            alert_users_query = alert_users_query.filter(models.Alert.owner.in_(patient_usernames))

        total_users = alert_users_query.count()
        total_pages = max(1, (total_users + page_size - 1) // page_size)
        if page > total_pages:
            page = total_pages
        alert_users = (
            alert_users_query
            .offset((page - 1) * page_size)
            .limit(page_size)
            .all()
        )
        return templates.TemplateResponse("dashboard.html", {
            "request": request,
            "username": username,
            "role": role,
            "active_tab": "alerts",
            "alert_users": alert_users,
            "selected_user": None,
            "current_page": page,
            "total_pages": total_pages
        })
    # 情况2：普通用户 或 医生/管理员选定了具体报警用户
    else:
        query = db.query(models.Alert)

        # 普通用户 → 仅看自己
        if role == "user":
            query = query.filter(models.Alert.owner == username)

        # 医生 → 查看某个病人的报警
        elif role == "doctor":
            doctor = db.query(models.User).filter(models.User.username == username).first()
            patient_usernames = [
                p.username for p in db.query(models.User)
                .filter(models.User.role == "user", models.User.doctor_id == doctor.id)
            ]
            # 如果带 ?user 参数，则只看该病人
            if user:
                if user not in patient_usernames:
                    return RedirectResponse(url="/alerts", status_code=303)
                query = query.filter(models.Alert.owner == user)
            else:
                query = query.filter(models.Alert.owner.in_(patient_usernames))
        # 管理员 / 超级管理员：如果带 user 参数，就过滤特定用户
        elif user:
            query = query.filter(models.Alert.owner == user)
        total_alerts = query.count()
        total_pages = max(1, (total_alerts + page_size - 1) // page_size)
        if page > total_pages:
            page = total_pages
        alerts = (
            query.order_by(models.Alert.timestamp.desc())
            .offset((page - 1) * page_size)
            .limit(page_size)
            .all()
        )
        return templates.TemplateResponse("dashboard.html", {
            "request": request,
            "username": username,
            "role": role,
            "active_tab": "alerts",
            "alerts": alerts,
            "selected_user": user,
            "current_page": page,
            "total_pages": total_pages
        })
# ---------------- 解决报警 ----------------
@router.post("/alerts/resolve_all/{target_username}")
def resolve_all_alerts(
    target_username: str,
    request: Request,
    db: Session = Depends(get_db)
):
    """医生批量处理某个用户的全部报警"""
    username, role = get_current_user_info(request)
    if not username:
        return RedirectResponse(url="/login", status_code=303)

    # 仅医生允许批量处理
    if role != "doctor":
        return JSONResponse({"error": "无权限操作"}, status_code=403)

    # 查找医生本人
    doctor = db.query(models.User).filter(models.User.username == username).first()
    if not doctor:
        return JSONResponse({"error": "医生身份无效"}, status_code=400)

    # 验证目标用户是否是该医生的病人
    patient = db.query(models.User).filter(
        models.User.username == target_username,
        models.User.doctor_id == doctor.id
    ).first()

    if not patient:
        return JSONResponse({"error": "无权限处理该患者报警"}, status_code=403)

    # 更新该患者的所有未处理报警
    updated = (
        db.query(models.Alert)
        .filter(models.Alert.owner == target_username, models.Alert.resolved == False)
        .update({models.Alert.resolved: True})
    )
    db.commit()
    return JSONResponse({
        "message": f"已处理 {updated} 条报警",
        "username": target_username
    })
#----------跳转报警心电数据------------
@router.get("/api/ecg_record/{record_id}")
def api_get_ecg_record(record_id: int, db: Session = Depends(get_db)):
    record = db.query(ECGRecord).filter(ECGRecord.id == record_id).first()
    if not record:
        return {"error": "Record not found"}
    return {
        "id": record.id,
        "device_id": record.device_id,
        "data": record.data or "",
        "start_time": record.start_time.strftime("%Y-%m-%d %H:%M:%S") if record.start_time else ""
    }
# ---------------- 用户管理（管理员/超级管理员） ----------------
@router.get("/users", response_class=HTMLResponse)
def users_page(request: Request, db: Session = Depends(get_db), q: str = None, msg: str = None):
    username, role = get_current_user_info(request)
    if not username:
        return RedirectResponse(url="/login", status_code=303)
    if role not in ["admin", "superadmin"]:
        return RedirectResponse(url="/", status_code=303)

    query = db.query(models.User)
    if role == "superadmin":
        query = query.filter(models.User.username != username)
    elif role == "admin":
        query = query.filter(
            models.User.role.notin_(["admin", "superadmin"]),
            models.User.username != username
        )
    if q:
        query = query.filter(models.User.username.contains(q))
    users = query.order_by(models.User.id).all()

    return templates.TemplateResponse("dashboard.html", {
        "request": request, "username": username, "role": role,
        "users": users, "search_q": q or "", "msg": msg, "active_tab": "users"
    })
# ---------------- 修改用户角色 ----------------
@router.post("/users/update_role")
def update_user_role(request: Request, username: str = Form(...), role: str = Form(...), db: Session = Depends(get_db)):
    current_name, current_role = get_current_user_info(request)
    if not current_name:
        return RedirectResponse(url="/login", status_code=303)
    if current_role not in ["admin", "superadmin"]:
        return RedirectResponse(url="/", status_code=303)
    user = db.query(models.User).filter(models.User.username == username).first()
    if not user or user.role == "superadmin":
        return RedirectResponse(url="/users", status_code=303)
    if current_role == "admin" and role == "admin":
        return templates.TemplateResponse("success.html", {
            "request": request, "title": "操作失败",
            "message": "管理员无权分配管理员角色",
            "redirect_url": "/users", "status": "error"
        })
    user.role = role
    db.commit()
    return templates.TemplateResponse("success.html", {
        "request": request, "title": "修改成功",
        "message": f"已成功将用户「{username}」的角色修改为「{role}」。",
        "redirect_url": "/users", "status": "success"
    })
# ---------------- 删除用户 ----------------
@router.get("/users/delete/{username}")
def delete_user(username: str, request: Request, db: Session = Depends(get_db)):
    current_name, current_role = get_current_user_info(request)
    if not current_name:
        return RedirectResponse(url="/login", status_code=303)
    user = db.query(models.User).filter(models.User.username == username).first()
    if not user:
        return RedirectResponse(url="/users", status_code=303)
    if user.username == current_name or user.role == "superadmin":
        return RedirectResponse(url="/users", status_code=303)
    db.delete(user)
    db.commit()
    return RedirectResponse(url="/users", status_code=303)
